import java.util.*;

/**
 * This superclass represent a generic publication.
 * 
 */
public class Publications {

	private final String title, issn, isbn;
	private final int year;
	private List<Author> authors;
	private boolean cited;
	private int nCite = 0;
	private List<CitationsForYear> citY;

	/**
	 * Construct a Publications object with the specified list of author, title, 
     * year of publication, ISSN code and ISBN code.
     * The ISSN code must be a numeric string of 8 character.
     * The ISBN code must be a numeric string of 13 character
     * ISSN and ISBN code can also be initialized at null.
     * 
	 * @param theAuthors the list of author object.
     * @param aTitle the publication title.
     * @param aYear the year of publication.
     * @param aIssn the ISSN code. 
     * @param aIsbn the ISBN code.
	 */
	public Publications(List<Author> theAuthors, String aTitle, int aYear,
			String aIssn, String aIsbn) {
		Calendar cal = new GregorianCalendar();
		if (theAuthors.size() == 0 || aTitle.equals("") || aYear < 1000
				|| aYear > cal.get(Calendar.YEAR))
			throw new IllegalArgumentException();
		else {
			this.authors = theAuthors;
			this.title = aTitle;
			this.year = aYear;
			this.cited = false;
		}
		if (aIssn == null || (aIssn.length() == 8 && aIssn.matches("[0-9]*")))
			this.issn = aIssn;
		else
			throw new IllegalArgumentException();
		if ((aIsbn == null)
				|| (aIsbn.length() == 13 && aIsbn.matches("[0-9]*")))
			this.isbn = aIsbn;
		else
			throw new IllegalArgumentException();
		citY = new ArrayList<CitationsForYear>();
	}

	@Override
	/**
	 * Return the string representation of the publication.
	 * 
	 * @return the string representation.
	 */
	public String toString() {
		return "title=" + title + ", issn=" + issn + ", isbn=" + isbn
				+ ", year=" + year + ", authors=" + authors.toString() + " "
				+ citY.toString();
	}

	/**
	 * Add the number of citation in a specific year.
	 * The number of citations  a positive integer.
	 * The year of citation have to be contain from the year of publication until 
	 * the current year.
	 * 
	 * @param aYear the year of citation.
	 * @param cit the number of citations.
	 */
	public void addCit(int aYear, int cit) {
		boolean mark = true;
		Calendar cal = new GregorianCalendar();
		if (cit>= 0 && aYear >= year && aYear <= cal.get(Calendar.YEAR)) {
			for (int i = 0; i < citY.size(); i++) {
				if (citY.get(i).getYear() == aYear) {
					citY.get(i).setnCite(cit + citY.get(i).getnCite());
					mark = false;
				}
			}
			if (mark) {
				CitationsForYear temp = new CitationsForYear(aYear, cit);
				citY.add(temp);
				this.cited = true;
				Collections.sort(citY);
			}
		} else
			throw new IllegalArgumentException("Incorrect Year or number of Citations");
	}

	/**
	 * @return the number of citations
	 */
	public int getnCite() {
		return nCite;
	}

	/**
	 * @return the author
	 */
	public List<Author> getAuthors() {
		return authors;
	}

	/**
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * @return the year of the publication
	 */
	public int getYear() {
		return year;
	}

	/**
	 * @return the issn code of the publication
	 */
	public String getIssn() {
		return issn;
	}

	/**
	 * @return the isbn code of the publication
	 */
	public String getIsbn() {
		return isbn;
	}

	/**
	 * @return the list of the author
	 */
	public List<Author> getAuthorsList() {
		return authors;
	}

	/**
	 * @return true if publication was cited
	 */
	public boolean getcited() {
		return cited;
	}

	/**
	 * @return the list of citation sorted by year
	 * */
	public List<CitationsForYear> getCitY() {
		return citY;
	}

	@Override
	/**
	 * Compares this object against the specified object. The result is true if and only if the argument is not null 
	 * and is a Publications object that represents the same publication of this object. Two publications
	 * are equals if and only if ISSN, ISBN, title and authors are equals.
	 * 
	 * @param obj the Object to compare to this against.
	 * @return true if the objects are the same, false otherwise.
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj instanceof Publications) {
			Publications other = (Publications) obj;
			if (this.isbn != null && this.issn != null) {
				if (this.isbn.equals(other.isbn)
						&& this.issn.equals(other.issn)
						&& this.title.equalsIgnoreCase(other.title)
						&& this.authors.equals(other.authors))
					return true;
			}
			if (this.isbn != null) {
				if (this.isbn.equals(other.isbn)
						&& this.title.equalsIgnoreCase(other.title)
						&& this.authors.equals(other.authors))
					return true;
			}
			if (this.issn != null) {
				if (this.issn.equals(other.issn)
						&& this.title.equalsIgnoreCase(other.title)
						&& this.authors.equals(other.authors))
					return true;
			}
		}
		return false;
	}
}